﻿using ImageProcessor;
using ImageProcessor.Imaging.Formats;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.WindowsAzure.Storage.Blob;
using Sino.CapacityCloud.Repositories.Models;
using Sino.CapacityCloud.Services;
using Sino.WebApi.Framework.Core.Filters;
using System;
using System.Drawing;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace Sino.CapacityCloud.WebApi.ApiControllers
{

    public class StorageController
        : ApiController<StorageController>
    {

        private readonly IAzureStorageService _azureStorageService;

        public StorageController(
            IHostingEnvironment env,
            IApplicationEnvironment applicationEnvironment,
            IDistributedCache cache,
            ITokenGenertationService tokenGenertationService,
            ApplicationDbContext dbContext,
            ApplicationUserManager userManager,
            ApplicationRoleManager roleManager,
            ApplicationSignInManager signInManager,
            ILoggerFactory loggerFactory,
            IAzureStorageService azureStorageService)
            : base(env, applicationEnvironment, cache, tokenGenertationService, dbContext, userManager, roleManager, signInManager, loggerFactory)
        {
            this._azureStorageService = azureStorageService;
        }

        public async Task<JsonResult> AquireStorageSharedSigniture(string containerName, TimeSpan? expireTime = null)
        {
            try
            {
                var user = await this.UserManager.FindByNameAsync(this.User.Identity.Name);
                if (user != null)
                {
                    // If the container doesn't exist, we will create it.
                    var currentDateTime = DateTime.UtcNow;
                    expireTime = expireTime ?? TimeSpan.FromDays(1);
                    var expireDateTime = currentDateTime + expireTime;
                    var sas = await this._azureStorageService.GenerateShareAccessSignitureAsync(containerName,
                        SharedAccessBlobPermissions.Read |
                        SharedAccessBlobPermissions.Write |
                        SharedAccessBlobPermissions.List |
                        SharedAccessBlobPermissions.Add |
                        SharedAccessBlobPermissions.Create,
                        null, expireDateTime);
                    var response = new AquireStorageSharedSignitureResponse()
                    {
                        ContainerName = containerName,
                        StorageSharedSigniture = sas,
                        Expire = expireTime.Value
                    };
                    return await this.PackageResultAsync(response);
                }
                throw new SystemException($"Failed to find the specified ApplicationUser object with querying name {this.User?.Identity?.Name}.");
            }
            catch (Exception ex)
            {
                this._logger.LogError($"Failed to generate a sas for container name {containerName} because: {ex.Message + Environment.NewLine + ex.StackTrace}");
                return await this.PackageResultAsync<AquireStorageSharedSignitureResponse>(ex);
            }
        }

        [SupressTokenValidation]
        [SupressUserLogin]
        public async Task<ActionResult> GetSmallImage(string url, int height = 64, int width = 64)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(url?.Decrypt("")))
                {
                    using (var client = new HttpClient())
                    {
                        using (var inputStream = await client.GetStreamAsync(url))
                        {
                            using (var outputStream = new MemoryStream())
                            {
                                using (var imageFactory = new ImageFactory())
                                {
                                    // Load, resize, set the format and quality and save an image.
                                    imageFactory
                                        .Load(inputStream)
                                        .Resize(new Size(width, height))
                                        .Format(new JpegFormat())
                                        .Quality(70)
                                        .Save(outputStream);
                                }
                                outputStream.Flush();
                                return this.File(outputStream, "image/jpeg");
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this._logger.LogError(ex.Message + Environment.NewLine + ex.StackTrace);
            }
            return this.HttpNotFound();
        }

    }

}